/*  For our final example, server5.c, 
    we include the sys/time.h and sys/ioctl.h headers in place of signal.h
    in our last program and declare some extra variables to deal with select.  */

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

#define MAXEVENTS 64

int main()
{
    int server_sockfd, client_sockfd;
    int server_len, client_len;
    struct sockaddr_in server_address;
    struct sockaddr_in client_address;
    int result;
	int fdMax = 0;
	int i;
	int flag;
	struct epoll_event event;
	struct epoll_event *events;
	int efd;
	int ret;

/*  Create and name a socket for the server.  */

    server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

	flag = 1;
	int len = sizeof(int);
	if (setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, len) < 0)
	{
		perror("setsockopt SO_REUSEADDR failure\n");
	}

    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(9752);
    server_len = sizeof(server_address);

    bind(server_sockfd, (struct sockaddr *)&server_address, server_len);

    listen(server_sockfd, 5);
	
	efd = epoll_create1(0);
	if (efd == -1)
		perror("epoll_create error!\n");

	event.data.fd = server_sockfd;
	event.events = EPOLLIN;
	ret = epoll_ctl (efd, EPOLL_CTL_ADD, server_sockfd, &event);
	if (ret == -1)
		perror("epoll_ctl error!\n");

	events = calloc (MAXEVENTS, sizeof event);

/*  Now wait for clients and requests.
    Since we have passed a null pointer as the timeout parameter, no timeout will occur.
    The program will exit and report an error if select returns a value of less than 1.  */

    while(1) {
        char *ch;
		ch = malloc(100000);
        int i;
        
		int nread;
		int n;
		int s;

/*  Once we know we've got activity,
    we find which descriptor it's on by checking each in turn using FD_ISSET.  */

		printf("\nepoll_wait ...... \n");
		n = epoll_wait(efd, events, MAXEVENTS, -1);
		printf("epoll_wait activity!\n");

        for(i = 0; i < n ; i++) {

			if (events[i].events & EPOLLERR ||
					events[i].events & EPOLLHUP) {
				fprintf (stderr, "epoll error\n");
				close (events[i].data.fd);
				continue;
			}

			if (events[i].events & EPOLLIN) {
				if (server_sockfd == events[i].data.fd && 
						events[i].events & EPOLLIN) {
					/*accept new client and add in epoll fd*/

					client_len = sizeof(client_address);
					client_sockfd = accept(server_sockfd, 
						  (struct sockaddr *)&client_address, &client_len);

					event.data.fd = client_sockfd;
					event.events = EPOLLIN;
					s = epoll_ctl(efd, EPOLL_CTL_ADD, client_sockfd, &event);
					printf("add new client %d\n", client_sockfd);

					if (s == -1)
						perror ("epoll_ctl");
				}	
				else {
					int rdnum;	
					int rdfd;

					rdfd = events[i].data.fd;

					printf("process client %d ......\n",rdfd); 
					printf("recv %d bytes ...\n", 5);
					rdnum = read(rdfd, ch, 5);
					if (rdnum < 0)
						printf("%s\n", strerror(errno));
					printf("recv client %d \"%d\"\n", rdfd, rdnum);
					printf("sleep few seconds...\n");
					sleep(1);
				}
			}//if EPOLLIN
		}
	}//while
}
